home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Gfx / Edit / TSMorph / src / Frames.c < prev    next >
C/C++ Source or Header  |  1994-10-30  |  10KB  |  339 lines

  1. // TSMorph - Amiga Morphing program
  2. // Copyright (C) © 1993  Topicsave Limited
  3.  
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // any later version.
  8.  
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13.  
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. // mpaddock@cix.compulink.co.uk
  19.  
  20. // include headers if not precompiled
  21. #ifndef TSMORPH_H
  22. #include "TSMorph.h"
  23. #endif
  24.  
  25. LONG OldFrame;        // Previous frame number
  26.  
  27. /* Go to the first frame
  28.  * the return value is that used by the main message loop
  29.  */
  30. int
  31. FirstFrame(void) {
  32.     OldFrame=FrameNumber;                // Store old frame
  33.     FrameNumber = GetNumber(TSMorphGadgets[GDX_Start]);    // get starting frame
  34.     if (FrameNumber != OldFrame) {    // if different
  35.         return ReopenPictures();        // try and move to new frame
  36.     }
  37.     return 1;
  38. }
  39.  
  40. /* Go to the previous frame
  41.  * See FirstFrame()
  42.  */
  43. int
  44. PrevFrame(void) {
  45.     OldFrame=FrameNumber;
  46.     if (FrameNumber > GetNumber(TSMorphGadgets[GDX_Start])) {
  47.         --FrameNumber;    // previous frame
  48.         return ReopenPictures();
  49.     }
  50.     return 1;
  51. }
  52.  
  53. /* Go to the previous frame
  54.  * See FirstFrame()
  55.  */
  56. int
  57. GotoFrame(void) {
  58.     OldFrame=FrameNumber;
  59.     GetFrameNumber();    // Request frame number
  60.     if (FrameNumber != OldFrame) {
  61.         return ReopenPictures();
  62.     }
  63.     return 1;
  64. }
  65.  
  66. /* Go to the next frame
  67.  * See FirstFrame()
  68.  */
  69. int
  70. NextFrame(void) {
  71.     OldFrame=FrameNumber;    // next determine last frame number
  72.     if (FrameNumber < (GetNumber(TSMorphGadgets[GDX_Start]) + GetNumber(TSMorphGadgets[GDX_Frames]) -1)) {
  73.         ++FrameNumber;
  74.         return ReopenPictures();
  75.     }
  76.     return 1;
  77. }
  78.  
  79. /* Go to the last frame
  80.  * See NextFrame()
  81.  */
  82. int
  83. LastFrame(void) {
  84.     OldFrame=FrameNumber;
  85.     FrameNumber = GetNumber(TSMorphGadgets[GDX_Start]) + GetNumber(TSMorphGadgets[GDX_Frames]) - 1;
  86.     if (FrameNumber != OldFrame) {
  87.         return ReopenPictures();
  88.     }
  89.     return 1;
  90. }
  91.  
  92. /* Request frame number
  93.  * returns TRUE if not cancelled
  94.  * selected frame is stored in FrameNumber
  95.  * This could use a nice sliding gadet requester - actually uses reqtools
  96.  */
  97. BOOL
  98. GetFrameNumber(void) {
  99.     LONG     Frames, Start;            // Number of frames and starting frame
  100.     ULONG ret = 2;                    // loop flag
  101.     struct AmigaGuideMsg *agm;    // for help
  102.     ULONG signals;                    // signals to wait on
  103.     struct rtHandlerInfo *rth;    // reqtools stuff
  104.  
  105.     Frames = GetNumber(TSMorphGadgets[GDX_Frames]);    // Get frames and start frame
  106.     Start = GetNumber(TSMorphGadgets[GDX_Start]);
  107.     if (Frames > 1) {                // No point displaying requester if 0 or 1 frame
  108.         // Determine Current frame number in correct range, using previously held value
  109.         FrameNumber = max(Start,FrameNumber);
  110.         FrameNumber = min(Start+Frames-1,FrameNumber);
  111.         DisableWindows(DI_GetFrame);    // Disable all other windows
  112.         while (ret == 2) {                // loop until Ok or Cancel (keep looping on Help)
  113.                                                 // if no amigaguide then 2 will never be returned
  114.             ret = CALL_HANDLER;            // reqtools stuff
  115.             if (rtGetLong((ULONG *)&FrameNumber,MyGetMsg(MSG_FRAMENO),NULL,
  116.                                 RT_ReqHandler,        &rth,
  117.                                 RT_Window,            TSMorphWnd,            // same screen
  118.                                 RTGL_Min,            Start,
  119.                                 RTGL_Max,            Start+Frames-1,
  120.                                 RTGL_ShowDefault,    TRUE,
  121.                                 RT_Underscore,     '_',
  122.                                 RTGL_GadFmt,         handle?MyGetMsg(MSG_OKHC):MyGetMsg(MSG_OKC),    // if amigaguide then help gadget
  123.                                 TAG_END) == CALL_HANDLER) {    // Opened requester
  124.                 while (ret == CALL_HANDLER) {                    // Loop well no gadget selected
  125.                     if (!rth->DoNotWait) {                        // Wait if poss.
  126.                         signals = Wait(rth->WaitMask | ASig);
  127.                     }
  128.                     ret = rtReqHandlerA(rth,signals,NULL);    // get gadget etc.
  129.                     if (ret == 2) {                                // help gadget
  130.                         help(H_FrameNumber);
  131.                     }
  132.                     if (signals & ASig) {                        // amigaguide message
  133.                           while (agm = GetAmigaGuideMsg(handle)) {
  134.                              ReplyAmigaGuideMsg(agm);
  135.                          }
  136.                      }
  137.                 }
  138.             }
  139.             else {                        // otherwise error so default Cancel
  140.                 ret = FALSE;
  141.             }
  142.         }
  143.         EnableWindows();    // enable all the windows
  144.     }
  145.     else {
  146.         if (!Frames) {    // number of frames = 0 so error
  147.             Error(MyGetMsg(MSG_MUST1F),MyGetMsg(MSG_OK),NULL,HE_OneFrame);
  148.             ret = FALSE;
  149.         }
  150.         else {            // number of frames = 1 so only one choice
  151.             FrameNumber = Start;
  152.             ret = TRUE;
  153.         }
  154.     }
  155.     return (BOOL)ret;    // Cancel gadget is 0
  156. }
  157.  
  158. /* Closes and reopens images using new frame (in FrameNumber)
  159.  * the return value is that used by the main message loop
  160.  */
  161. int
  162. ReopenPictures(void) {
  163.     char buffer[257];    // Work buffer for points file name
  164.     LONG KeepFrame;    // Temporary frame number
  165.     if (!Saved) {        // if not saved then reset frame number and suggest user saves
  166.      KeepFrame = FrameNumber;
  167.      FrameNumber = OldFrame;
  168.      if (!SaveRequester()) {
  169.       return 1;            // user cancelled
  170.      }
  171.      FrameNumber = KeepFrame;    // either saved or abandoned so go to new frame
  172.     }
  173.     // Disable the windows and delete all the points
  174.     DisableWindows(DI_NextFrame);
  175.     DeleteAllPoints();
  176.     // Try and reopen image one and two
  177.     if (ReopenAPicture(GetString(TSMorphGadgets[GDX_FileOne]),&Pic1)) {
  178.         if (ReopenAPicture(GetString(TSMorphGadgets[GDX_FileTwo]),&Pic2)) {
  179.             // if ok then set up points filename and try and open
  180.             strcpy(TempFilename,savedfilename);
  181.             strcat(TempFilename,".%03ld");
  182.             sprintf(buffer,TempFilename,FrameNumber);
  183.             MyOpen(buffer,TRUE,FALSE);    // Note! do not complain if no points file for thisframe (yet)
  184.             // enable the windows
  185.             EnableWindows();
  186.             // This is nasty!! (and probably unnecessary)
  187.             // but CWTitle is already held as the screen title,
  188.             // so do not want to be writing whilst intuition is reading
  189.             // Probably better to just call SetWindowTitles twice (first time to nothing)
  190.             // But that could cause the screen to flicker?
  191.             Forbid();
  192.             sprintf(CWTitle,MyGetMsg(MSG_TSMFRAME),FrameNumber);
  193.             Permit();
  194.             SetWindowTitles(ControlWindow,(UBYTE *)-1,CWTitle);
  195.             return 1;    // It worked
  196.         }
  197.     }
  198.     EnableWindows();
  199.     return 3;            // It did not work, so windows are closed, but keep going
  200. }
  201.  
  202. /* Opens an image in an (already) open window
  203.  * This is all very convoluted stuff!
  204.  * returns    : TRUE or FALSE for sucess failure
  205.  * filename    : Name of file
  206.  * pic        : pointer to a structure to hold all the stuff
  207.  */
  208. BOOL
  209. ReopenAPicture(char *filename,struct Picture *pic) {
  210.  char dirname[257];            // filename storage
  211.  char *e             = NULL;    // first part of error message
  212.  char *e1             = NULL;    // 2nd part of error message
  213.  LONG hnum            = 0;        // Help number for error
  214.  struct BitMap *OldBitMap = NULL;    // BitMap to keep
  215.  
  216.  // Set up new filename and display as screen title
  217.  // window title is done later (does not sound good?)
  218.  sprintf(dirname,filename,FrameNumber);
  219.  Forbid();            // Forbid whilst change window title - Nasty!!
  220.  strcpy(pic->filename,dirname);
  221.  Permit();
  222. if (EGS) {
  223.  // Unload current frame (keeping bitmap)
  224.  unloadbrush(pic->ilbm);
  225.  // Try and load new brush - if this fails then flag error
  226.  if (!MyLoadBrush(pic,dirname)) {
  227.   e = (char *)-1;
  228.  }
  229.  if (!e) {
  230.   // fail if frame is not the same size as previous
  231.   if ((pic->width != Width) ||
  232.         (pic->height != Height)) {
  233.     e = MyGetMsg(MSG_FRAMESIZE);
  234.     hnum = HE_FAllSize;
  235.   }
  236.   else {
  237.    EI_SetWindowTitles(pic->EGS_Win,FilePart(pic->filename),pic->filename);
  238.    EG_CopyBitMapRastPort(pic->EGS_BitMap,pic->EGS_Win->RPort,0,0,pic->width,pic->height,0,0);
  239.    E_DisposeBitMap(pic->EGS_BitMap);
  240.    pic->EGS_BitMap = NULL;
  241.   }
  242.  }
  243.  else {
  244.   // failed loading new image
  245.   // so close file
  246.   closeifile(&(pic->ilbm->ParseInfo));
  247.   // set up error stuff
  248.   e = MyGetMsg(MSG_FAILLOAD);
  249.   e1 = dirname;
  250.   hnum = HE_LoadImage;
  251.  }
  252. }
  253. else {
  254.  SetWindowTitles(pic->Win,(UBYTE *)-1,pic->filename);
  255.  // if we do not allow zoom then the super bitmap is the actual bit map
  256.  // so initialise so we do not lose it when we unload the brush
  257.  if (!ZoomAllowed) {
  258.   // Zero out current bitmap picture
  259.   OldBitMap = pic->ilbm->brbitmap;
  260.   pic->ilbm->brbitmap = NULL;
  261.  }
  262.  // Unload current frame (keeping bitmap)
  263.  unloadbrush(pic->ilbm);
  264.  // Try and load new brush - if this fails then flag error
  265.  if (!MyLoadBrush(pic,dirname)) {
  266.   e = (char *)-1;
  267.  }
  268.  if (!e) {
  269.   // fail if frame is not the same size as previous
  270.   if ((pic->ilbm->Bmhd.w != Width) ||
  271.         (pic->ilbm->Bmhd.h != Height)) {
  272.    // if no zoom allowed then reset the bitmap to the original - freeing the new one
  273.     if (!ZoomAllowed) {
  274.      freebitmap(pic->ilbm);
  275.      pic->ilbm->brbitmap = OldBitMap;
  276.     }
  277.     e = MyGetMsg(MSG_FRAMESIZE);
  278.     hnum = HE_FAllSize;
  279.   }
  280.   else {
  281.     SetWindowTitles(pic->Win,FilePart(pic->filename),pic->filename);    // This refreshes the titles
  282.     if (ZoomAllowed) {
  283.     // If we allow zoom then reset up BitScale stuff and scale or copy
  284.      pic->BitScaleArgs.bsa_SrcBitMap     = pic->ilbm->brbitmap;
  285.      /* Either scale image 2x or straight copy    */
  286.      if (Zoom) {
  287.       BitMapScale(&(pic->BitScaleArgs));
  288.      }
  289.      else {
  290.       BltBitMap(pic->ilbm->brbitmap,0,0,
  291.                       &(pic->BitMap),0,0,
  292.                       pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,
  293.                       0xC0,0xff,NULL);
  294.      }
  295.     }
  296.     else {
  297.      // Zoom is not allowed - so copy the new bit map to the old bit map
  298.      BltBitMap(pic->ilbm->brbitmap,0,0,
  299.                     OldBitMap,0,0,
  300.                       pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,
  301.                       0xC0,0xff,NULL);
  302.      // free the new bit map and set the image back
  303.      freebitmap(pic->ilbm);
  304.      pic->ilbm->brbitmap = OldBitMap;
  305.      // All because we can not change the bitmap of a super bitmap window
  306.     }
  307.     // Resync the display to the new bitmap display
  308.     LockLayerRom(pic->Win->RPort->Layer);
  309.     CopySBitMap(pic->Win->RPort->Layer);
  310.     UnlockLayerRom(pic->Win->RPort->Layer);
  311.   }
  312.  }
  313.  else {
  314.   // failed loading new image
  315.   // so close file
  316.   closeifile(&(pic->ilbm->ParseInfo));
  317.   if (!ZoomAllowed) {
  318.    // if no zoom allowed then free new bit map and restore old
  319.     freebitmap(pic->ilbm);
  320.     pic->ilbm->brbitmap = OldBitMap;
  321.   }
  322.   // set up error stuff
  323.   e = MyGetMsg(MSG_FAILLOAD);
  324.   e1 = dirname;
  325.   hnum = HE_LoadImage;
  326.  }
  327. }
  328.  // display error (if required) and return status
  329.  if (e) {
  330.   if (e != (char *)-1) {    // do not think this is possible?
  331.    Error(e,MyGetMsg(MSG_OK),e1,hnum);    // we can actually display two error message
  332.   }                                // as MyLoadBrush() may have already displayed one
  333.   return FALSE;
  334.  }
  335.  else {
  336.   return TRUE;
  337.  }
  338. }
  339.